home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2017 October / PCgo 10-2017 CD-ROM Germany.iso / nw.pak / Unnamed File 004913.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  9.2 KB  |  289 lines

  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. // This module implements a wrapper for a guestview that manages its
  6. // creation, attaching, and destruction.
  7.  
  8. var GuestViewInternal =
  9.     require('binding').Binding.create('guestViewInternal').generate();
  10. var GuestViewInternalNatives = requireNative('guest_view_internal');
  11.  
  12. // Possible states.
  13. var GUEST_STATE_ATTACHED = 2;
  14. var GUEST_STATE_CREATED = 1;
  15. var GUEST_STATE_START = 0;
  16.  
  17. // Error messages.
  18. var ERROR_MSG_ALREADY_ATTACHED = 'The guest has already been attached.';
  19. var ERROR_MSG_ALREADY_CREATED = 'The guest has already been created.';
  20. var ERROR_MSG_INVALID_STATE = 'The guest is in an invalid state.';
  21. var ERROR_MSG_NOT_ATTACHED = 'The guest is not attached.';
  22. var ERROR_MSG_NOT_CREATED = 'The guest has not been created.';
  23.  
  24. // Contains and hides the internal implementation details of |GuestView|,
  25. // including maintaining its state and enforcing the proper usage of its API
  26. // fucntions.
  27.  
  28. function GuestViewImpl(viewType, guestInstanceId) {
  29.   if (guestInstanceId) {
  30.     this.id = guestInstanceId;
  31.     this.state = GUEST_STATE_CREATED;
  32.   } else {
  33.     this.id = 0;
  34.     this.state = GUEST_STATE_START;
  35.   }
  36.   this.actionQueue = [];
  37.   this.contentWindow = null;
  38.   this.pendingAction = null;
  39.   this.viewType = viewType;
  40.   this.internalInstanceId = 0;
  41. }
  42.  
  43. // Callback wrapper that is used to call the callback of the pending action (if
  44. // one exists), and then performs the next action in the queue.
  45. GuestViewImpl.prototype.handleCallback = function(callback) {
  46.   if (callback) {
  47.     callback();
  48.   }
  49.   this.pendingAction = null;
  50.   this.performNextAction();
  51. };
  52.  
  53. // Perform the next action in the queue, if one exists.
  54. GuestViewImpl.prototype.performNextAction = function() {
  55.   // Make sure that there is not already an action in progress, and that there
  56.   // exists a queued action to perform.
  57.   if (!this.pendingAction && this.actionQueue.length) {
  58.     this.pendingAction = this.actionQueue.shift();
  59.     this.pendingAction();
  60.   }
  61. };
  62.  
  63. // Check the current state to see if the proposed action is valid. Returns false
  64. // if invalid.
  65. GuestViewImpl.prototype.checkState = function(action) {
  66.   // Create an error prefix based on the proposed action.
  67.   var errorPrefix = 'Error calling ' + action + ': ';
  68.  
  69.   // Check that the current state is valid.
  70.   if (!(this.state >= 0 && this.state <= 2)) {
  71.     window.console.error(errorPrefix + ERROR_MSG_INVALID_STATE);
  72.     return false;
  73.   }
  74.  
  75.   // Map of possible errors for each action. For each action, the errors are
  76.   // listed for states in the order: GUEST_STATE_START, GUEST_STATE_CREATED,
  77.   // GUEST_STATE_ATTACHED.
  78.   var errors = {
  79.     'attach': [ERROR_MSG_NOT_CREATED, null, ERROR_MSG_ALREADY_ATTACHED],
  80.     'create': [null, ERROR_MSG_ALREADY_CREATED, ERROR_MSG_ALREADY_CREATED],
  81.     'destroy': [null, null, null],
  82.     'detach': [ERROR_MSG_NOT_ATTACHED, ERROR_MSG_NOT_ATTACHED, null],
  83.     'setAutoSize': [ERROR_MSG_NOT_CREATED, null, null]
  84.   };
  85.  
  86.   // Check that the proposed action is a real action.
  87.   if (errors[action] == undefined) {
  88.     window.console.error(errorPrefix + ERROR_MSG_INVALID_ACTION);
  89.     return false;
  90.   }
  91.  
  92.   // Report the error if the proposed action is found to be invalid for the
  93.   // current state.
  94.   var error;
  95.   if (error = errors[action][this.state]) {
  96.     window.console.error(errorPrefix + error);
  97.     return false;
  98.   }
  99.  
  100.   return true;
  101. };
  102.  
  103. // Internal implementation of attach().
  104. GuestViewImpl.prototype.attachImpl = function(
  105.     internalInstanceId, viewInstanceId, attachParams, callback) {
  106.   // Check the current state.
  107.   if (!this.checkState('attach')) {
  108.     this.handleCallback(callback);
  109.     return;
  110.   }
  111.  
  112.   // Callback wrapper function to store the contentWindow from the attachGuest()
  113.   // callback, handle potential attaching failure, register an automatic detach,
  114.   // and advance the queue.
  115.   var callbackWrapper = function(callback, contentWindow) {
  116.     this.contentWindow = contentWindow;
  117.  
  118.     // Check if attaching failed.
  119.     if (this.contentWindow === null) {
  120.       this.state = GUEST_STATE_CREATED;
  121.     } else {
  122.       // Detach automatically when the container is destroyed.
  123.       GuestViewInternalNatives.RegisterDestructionCallback(internalInstanceId,
  124.                                                            function() {
  125.         if (this.state == GUEST_STATE_ATTACHED) {
  126.           this.contentWindow = null;
  127.           this.internalInstanceId = 0;
  128.           this.state = GUEST_STATE_CREATED;
  129.         }
  130.       }.bind(this));
  131.     }
  132.  
  133.     this.handleCallback(callback);
  134.   };
  135.  
  136.   attachParams['instanceId'] = viewInstanceId;
  137.   GuestViewInternalNatives.AttachGuest(internalInstanceId,
  138.                                        this.id,
  139.                                        attachParams,
  140.                                        callbackWrapper.bind(this, callback));
  141.  
  142.   this.internalInstanceId = internalInstanceId;
  143.   this.state = GUEST_STATE_ATTACHED;
  144. };
  145.  
  146. // Internal implementation of create().
  147. GuestViewImpl.prototype.createImpl = function(createParams, callback) {
  148.   // Check the current state.
  149.   if (!this.checkState('create')) {
  150.     this.handleCallback(callback);
  151.     return;
  152.   }
  153.  
  154.   // Callback wrapper function to store the guestInstanceId from the
  155.   // createGuest() callback, handle potential creation failure, and advance the
  156.   // queue.
  157.   var callbackWrapper = function(callback, guestInstanceId) {
  158.     this.id = guestInstanceId;
  159.  
  160.     // Check if creation failed.
  161.     if (this.id === 0) {
  162.       this.state = GUEST_STATE_START;
  163.     }
  164.  
  165.     this.handleCallback(callback);
  166.   };
  167.  
  168.   GuestViewInternal.createGuest(this.viewType,
  169.                                 createParams,
  170.                                 callbackWrapper.bind(this, callback));
  171.  
  172.   this.state = GUEST_STATE_CREATED;
  173. };
  174.  
  175. // Internal implementation of destroy().
  176. GuestViewImpl.prototype.destroyImpl = function(callback) {
  177.   // Check the current state.
  178.   if (!this.checkState('destroy')) {
  179.     this.handleCallback(callback);
  180.     return;
  181.   }
  182.  
  183.   if (this.state == GUEST_STATE_START) {
  184.     // destroy() does nothing in this case.
  185.     this.handleCallback(callback);
  186.     return;
  187.   }
  188.  
  189.   GuestViewInternal.destroyGuest(this.id,
  190.                                  this.handleCallback.bind(this, callback));
  191.  
  192.   this.contentWindow = null;
  193.   this.id = 0;
  194.   this.internalInstanceId = 0;
  195.   this.state = GUEST_STATE_START;
  196. };
  197.  
  198. // Internal implementation of detach().
  199. GuestViewImpl.prototype.detachImpl = function(callback) {
  200.   // Check the current state.
  201.   if (!this.checkState('detach')) {
  202.     this.handleCallback(callback);
  203.     return;
  204.   }
  205.  
  206.   GuestViewInternalNatives.DetachGuest(
  207.       this.internalInstanceId,
  208.       this.handleCallback.bind(this, callback));
  209.  
  210.   this.contentWindow = null;
  211.   this.internalInstanceId = 0;
  212.   this.state = GUEST_STATE_CREATED;
  213. };
  214.  
  215. // Internal implementation of setAutoSize().
  216. GuestViewImpl.prototype.setAutoSizeImpl = function(autoSizeParams, callback) {
  217.   // Check the current state.
  218.   if (!this.checkState('setAutoSize')) {
  219.     this.handleCallback(callback);
  220.     return;
  221.   }
  222.  
  223.   GuestViewInternal.setAutoSize(this.id, autoSizeParams,
  224.                                 this.handleCallback.bind(this, callback));
  225. };
  226.  
  227. // The exposed interface to a guestview. Exposes in its API the functions
  228. // attach(), create(), destroy(), and getId(). All other implementation details
  229. // are hidden.
  230. function GuestView(viewType, guestInstanceId) {
  231.   privates(this).internal = new GuestViewImpl(viewType, guestInstanceId);
  232. }
  233.  
  234. // Attaches the guestview to the container with ID |internalInstanceId|.
  235. GuestView.prototype.attach = function(
  236.     internalInstanceId, viewInstanceId, attachParams, callback) {
  237.   var internal = privates(this).internal;
  238.   internal.actionQueue.push(internal.attachImpl.bind(
  239.       internal, internalInstanceId, viewInstanceId, attachParams, callback));
  240.   internal.performNextAction();
  241. };
  242.  
  243. // Creates the guestview.
  244. GuestView.prototype.create = function(createParams, callback) {
  245.   var internal = privates(this).internal;
  246.   internal.actionQueue.push(internal.createImpl.bind(
  247.       internal, createParams, callback));
  248.   internal.performNextAction();
  249. };
  250.  
  251. // Destroys the guestview. Nothing can be done with the guestview after it has
  252. // been destroyed.
  253. GuestView.prototype.destroy = function(callback) {
  254.   var internal = privates(this).internal;
  255.   internal.actionQueue.push(internal.destroyImpl.bind(internal, callback));
  256.   internal.performNextAction();
  257. };
  258.  
  259. // Detaches the guestview from its container.
  260. // Note: This is not currently used.
  261. GuestView.prototype.detach = function(callback) {
  262.   var internal = privates(this).internal;
  263.   internal.actionQueue.push(internal.detachImpl.bind(internal, callback));
  264.   internal.performNextAction();
  265. };
  266.  
  267. // Adjusts the guestview's sizing parameters.
  268. GuestView.prototype.setAutoSize = function(autoSizeParams, callback) {
  269.   var internal = privates(this).internal;
  270.   internal.actionQueue.push(internal.setAutoSizeImpl.bind(
  271.       internal, autoSizeParams, callback));
  272.   internal.performNextAction();
  273. };
  274.  
  275. // Returns the contentWindow for this guestview.
  276. GuestView.prototype.getContentWindow = function() {
  277.   var internal = privates(this).internal;
  278.   return internal.contentWindow;
  279. };
  280.  
  281. // Returns the ID for this guestview.
  282. GuestView.prototype.getId = function() {
  283.   var internal = privates(this).internal;
  284.   return internal.id;
  285. };
  286.  
  287. // Exports
  288. exports.GuestView = GuestView;
  289.